/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package br.com.felinelayer.server.application;

import br.com.felinelayer.common.Message;
import br.com.felinelayer.common.Protocol;
import java.util.ArrayList;
import java.util.HashMap;

/**
 *
 * @author Vanius Roberto Bittencourt
 */
public abstract class Component<T extends Component> {

    public Application application;
    private int left = 0;
    private int top = 0;
    private int width = 0;
    private int height = 0;
    private int id = 0;
    private String text = "";
    private boolean updateFromOtherSide = false;

    public boolean isUpdateFromOtherSide() {
        return updateFromOtherSide;
    }

    public T setUpdateFromOtherSide( boolean updateFromOtherSide ) {
        this.updateFromOtherSide = updateFromOtherSide;
        return (T) this;
    }

    public T setText( String text ) {
        this.text = text;
        if ( !updateFromOtherSide )
            firePropertyChange( Protocol.PROPERTY_NAME_TEXT, text );
        return (T) this;
    }

    public String getText() {
        return text;
    }
    private Frame frame;

    public void setFrame( Frame frame ) {
        this.frame = frame;
    }
    private static final int PIXELS_PER_ROW = 28;
    private static final int PIXELS_PER_COL = 28;

    public T setRow( int row ) {
        setTop( ( row + 1 ) * PIXELS_PER_ROW );
        return (T) this;
    }

    public T setCol( int col ) {
        setLeft( ( col + 1 ) * PIXELS_PER_COL );
        return (T) this;
    }

    public int getLeft() {
        return left;
    }

    public T setLeft( int left ) {
        this.left = left;
        firePropertyChange( Protocol.PROPERTY_NAME_LEFT, left + "" );
        return (T) this;
    }

    public int getTop() {
        return top;
    }

    public T setTop( int top ) {
        this.top = top;
        firePropertyChange( Protocol.PROPERTY_NAME_TOP, top + "" );
        return (T) this;
    }

    public int getWidth() {
        return width;
    }

    public T setWidth( int width ) {
        this.width = width;
        firePropertyChange( Protocol.PROPERTY_NAME_WIDTH, width + "" );
        return (T) this;
    }

    public int getHeight() {
        return height;
    }

    public T setHeight( int height ) {
        this.height = height;
        firePropertyChange( Protocol.PROPERTY_NAME_HEIGHT, height + "" );
        return (T) this;
    }

    public int getId() {
        return id;
    }

    protected Message inquireMessage( Message message ) {
        message.setValueByName( Protocol.COMPONENT_ID, getId() );
        return application.inquire( message );
    }

    protected T sendMessage( Message message ) {
        message.setValueByName( Protocol.COMPONENT_ID, getId() );
        application.sendMessage( message );
        return (T) this;
    }
    
    protected void firePropertyChange( String propertyName, int value ) {
        firePropertyChange( propertyName, value + "" ) ;     
    }

    protected void firePropertyChange( String propertyName, String value ) {
        Message message = new Message( Protocol.MSG_NAME_COMPONENT_PROPERTY_CHANGE );
        message.setValueByName( Protocol.COMPONENT_ID, getId() );
        message.setValueByName( propertyName, value );
        inquireMessage( message );
    }

    /**
     * @param id the id to set
     */
    public T setId( int id ) {
        this.id = id;
        return (T) this;
    }
    private HashMap<String, ArrayList<IEventListener>> eventListeners = new HashMap<>();

    public T addEventListener( String eventName, IEventListener eventListener ) {
        ArrayList<IEventListener> l = eventListeners.get( eventName );
        if ( l == null )
            l = new ArrayList<>();
        if ( l.indexOf( l ) < 0 )
            l.add( eventListener );
        eventListeners.put( eventName, l );
        Message message = new Message( Protocol.EVENT_ADD_LISTENER );
        message.setValueByName( Protocol.EVENT_NAME, Protocol.EVENT_CLICK );
        sendMessage( message );
        return (T) this;
    }

    public void messageReceived( Message message ) {
        doMessageReceived(message);
        if ( !message.isPropertyExists( Protocol.EVENT_NAME ) )
            return;
        String eventName = message.getValueByName( Protocol.EVENT_NAME );
        ArrayList<IEventListener> l = eventListeners.get( eventName );
        if ( l == null )
            return;
        for ( IEventListener e : l )
            e.onEvent( this, eventName, message );
    }

    public void clearListeners() {
        eventListeners.clear();
    }

    public void destroy() {
        Message m = new Message().setName( Protocol.MSG_NAME_DESTROY_COMPONENT );
        sendMessage( m );
    }
    
    public abstract String getComponentClassName();

    protected void doMessageReceived(Message message) {
        
    }
}
